package org.eiahe.hr.salary.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.ehe.common.core.utils.MapstructUtils;
import org.ehe.common.core.utils.StringUtils;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.ehe.system.service.ISysDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.eiahe.hr.salary.domain.CashPayment;
import org.eiahe.hr.salary.domain.bo.CashPaymentBo;
import org.eiahe.hr.salary.domain.vo.CashPaymentVo;
import org.eiahe.hr.salary.mapper.CashPaymentMapper;
import org.eiahe.hr.salary.service.ICashPaymentService;
import org.eiahe.hr.salary.service.IEmployeePhoneAssociationService;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * 现金发放Service业务层处理
 *
 * @author zhangnn
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class CashPaymentServiceImpl implements ICashPaymentService {

    private final CashPaymentMapper baseMapper;
    private final ISysDeptService deptService;

    @Autowired
    private IEmployeePhoneAssociationService employeePhoneAssociationService;

    /**
     * 查询现金发放
     *
     * @param paymentId 现金发放ID
     * @return 现金发放
     */
    @Override
    public CashPaymentVo queryById(Long paymentId) {
        return baseMapper.selectVoById(paymentId);
    }

    /**
     * 查询现金发放列表
     *
     * @param bo 现金发放业务对象
     * @return 现金发放集合
     */
    @Override
    public List<CashPaymentVo> queryList(CashPaymentBo bo) {
        LambdaQueryWrapper<CashPayment> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    /**
     * 分页查询现金发放列表
     *
     * @param bo        现金发放业务对象
     * @param pageQuery 分页参数
     * @return 现金发放分页数据
     */
    @Override
    public TableDataInfo<CashPaymentVo> queryPageList(CashPaymentBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<CashPayment> lqw = buildQueryWrapper(bo);
        Page<CashPaymentVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 新增现金发放
     *
     * @param bo 现金发放业务对象
     * @return 是否成功
     */
    @Override
    public Boolean insertByBo(CashPaymentBo bo) {
        CashPayment add = MapstructUtils.convert(bo, CashPayment.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setPaymentId(add.getPaymentId());
        }
        return flag;
    }

    /**
     * 修改现金发放
     *
     * @param bo 现金发放业务对象
     * @return 是否成功
     */
    @Override
    public Boolean updateByBo(CashPaymentBo bo) {
        CashPayment update = MapstructUtils.convert(bo, CashPayment.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 批量删除现金发放
     *
     * @param ids 现金发放ID数组
     * @return 是否成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 领取现金
     *
     * @param paymentId 现金发放ID
     * @return 是否成功
     */
    @Override
    public Boolean receiveCash(Long paymentId) {
        CashPayment payment = baseMapper.selectById(paymentId);
        if (payment == null) {
            log.warn("现金发放记录不存在，paymentId: {}", paymentId);
            return false;
        }

        // 更新领取状态为已领取
        payment.setReceiveStatus("1");
        payment.setReceiveTime(new Date());
        return baseMapper.updateById(payment) > 0;
    }

    /**
     * 领取现金(带电子签字)
     *
     * @param paymentId         现金发放ID
     * @param receiverSignature 领取人电子签字
     * @return 是否成功
     */
    @Override
    public Boolean receiveCashWithSignature(Long paymentId, String receiverSignature) {
        CashPayment payment = baseMapper.selectById(paymentId);
        if (payment == null) {
            log.warn("现金发放记录不存在，paymentId: {}", paymentId);
            return false;
        }

        // 更新领取状态为已领取
        payment.setReceiveStatus("1");
        payment.setReceiverSignature(receiverSignature);
        payment.setReceiveTime(new Date());
        return baseMapper.updateById(payment) > 0;
    }

    /**
     * 领取现金(验证手机号后)
     *
     * @param paymentId         现金发放ID
     * @param receiverSignature 领取人电子签字
     * @param employeeNo        工号
     * @return 是否成功
     */
    @Override
    public Boolean receiveCashWithVerification(Long paymentId, String receiverSignature, String employeeNo) {
        // 检查员工手机号是否已验证
        if (!employeePhoneAssociationService.isPhoneNumberVerified(employeeNo)) {
            log.warn("员工手机号未验证，无法领取现金，employeeNo: {}", employeeNo);
            throw new RuntimeException("员工手机号未验证，无法领取现金");
        }

        CashPayment payment = baseMapper.selectById(paymentId);
        if (payment == null) {
            log.warn("现金发放记录不存在，paymentId: {}", paymentId);
            return false;
        }

        // 确保是该员工的现金发放记录
        if (!employeeNo.equals(payment.getEmployeeNo())) {
            log.warn("无权领取他人现金，employeeNo: {}", employeeNo);
            throw new RuntimeException("无权领取他人现金");
        }

        // 更新领取状态为已领取
        payment.setReceiveStatus("1");
        payment.setReceiverSignature(receiverSignature);
        payment.setReceiveTime(new Date());
        return baseMapper.updateById(payment) > 0;
    }

    /**
     * 构建查询条件
     *
     * @param bo 现金发放业务对象
     * @return 查询条件
     */
    private LambdaQueryWrapper<CashPayment> buildQueryWrapper(CashPaymentBo bo) {
        LambdaQueryWrapper<CashPayment> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getTenantId()), CashPayment::getTenantId, bo.getTenantId());
        lqw.eq(StringUtils.isNotBlank(bo.getEmployeeNo()), CashPayment::getEmployeeNo, bo.getEmployeeNo());
        lqw.eq(StringUtils.isNotBlank(bo.getBonusType()), CashPayment::getBonusType, bo.getBonusType());
        lqw.eq(bo.getPaymentTime() != null, CashPayment::getPaymentTime, bo.getPaymentTime());
        lqw.eq(StringUtils.isNotBlank(bo.getReceiveStatus()), CashPayment::getReceiveStatus, bo.getReceiveStatus());
        return lqw;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(CashPayment entity) {
        // 校验员工工号是否存在
        if (StringUtils.isBlank(entity.getEmployeeNo())) {
            throw new RuntimeException("员工工号不能为空");
        }

        // 校验发放金额必须大于0
        if (entity.getPaymentAmount() == null || entity.getPaymentAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new RuntimeException("发放金额必须大于0");
        }

        // 校验发放时间不能为空
        if (entity.getPaymentTime() == null) {
            throw new RuntimeException("发放时间不能为空");
        }

        // 校验状态合法性
        if (StringUtils.isNotBlank(entity.getReceiveStatus()) &&
                !"0".equals(entity.getReceiveStatus()) && !"1".equals(entity.getReceiveStatus())) {
            throw new RuntimeException("领取状态只能是0(未领取)或1(已领取)");
        }

        // 校验奖金类型不能为空
        if (StringUtils.isBlank(entity.getBonusType())) {
            throw new RuntimeException("奖金类型不能为空");
        }
    }
}
